package com.wifibrowser.lib;

import android.annotation.SuppressLint;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @author Administrator
 * @Email guoyil199@163.com
 * @version V1.0
 * @Date 2015年3月10日 上午10:15:58
 * @Title <pre>
 * todo
 * </pre>
 * @Description <pre>
 * An encapsulation of {@link Log}, enable log level and print log with
 * parameters.
 * </pre>
 */
public class Log {
	private static final String TAG = "LogCat";

	public static final int LEVEL_VERBOSE = 0;
	public static final int LEVEL_DEBUG = 1;
	public static final int LEVEL_INFO = 2;
	public static final int LEVEL_WARNING = 3;
	public static final int LEVEL_ERROR = 4;
	public static final int LEVEL_FATAL = 5;
	public static final int LEVEL_RELEASE = 6;

	private static int sLevel = LEVEL_VERBOSE;
	
	private static boolean isWrite=false;
	@SuppressLint("SimpleDateFormat")
	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	private Log() {
	}

	/**
	 * @return boolean is Debug
	 */
	public static boolean isDebug() {
		return sLevel < LEVEL_RELEASE;
	}
	
	public static void isWrite(boolean enWrite){
		isWrite=enWrite;
	}

	/**
	 * set log level, the level lower than this level will not be logged
	 * 
	 * @param level
	 */
	public static void setLogLevel(int level) {
		sLevel = level;
	}

	/**
	 * Send a DEBUG log message
	 * 
	 * @param tag
	 * @param msg
	 */
	public static void d(String msg) {
		if (sLevel > LEVEL_DEBUG) {
			return;
		}
		android.util.Log.d(TAG,buildMessage(msg));
	}

	/**
	 * Send a DEBUG log message
	 * 
	 * @param tag
	 * @param msg
	 */
	public static void d(String tag, String msg) {
		if (sLevel > LEVEL_DEBUG) {
			return;
		}
		android.util.Log.d(tag,buildMessage(msg));
	}

	/**
	 * Send a DEBUG log message
	 * 
	 * @param tag
	 * @param msg
	 * @param args
	 */
	public static void d(String tag, String msg, Object... args) {
		if (sLevel > LEVEL_DEBUG) {
			return;
		}
		if (args.length > 0) {
			msg = String.format(msg, args);
		}
		android.util.Log.d(tag,buildMessage(msg));
	}

	/**
	 * Send a DEBUG log message
	 * 
	 * @param tag
	 * @param msg
	 * @param throwable
	 */
	public static void d(String tag, String msg, Throwable throwable) {
		if (sLevel > LEVEL_DEBUG) {
			return;
		}
		android.util.Log.d(tag,buildMessage(msg),throwable);
	}

	/**
	 * Send an ERROR log message
	 * 
	 * @param tag
	 * @param msg
	 */
	public static void e(String msg) {
		if (sLevel > LEVEL_ERROR) {
			return;
		}
		android.util.Log.e(TAG,buildMessage(msg));
	}

	/**
	 * Send an ERROR log message
	 * 
	 * @param tag
	 * @param msg
	 */
	public static void e(String tag, String msg) {
		if (sLevel > LEVEL_ERROR) {
			return;
		}
		android.util.Log.e(tag,buildMessage(msg));
	}

	/**
	 * Send an ERROR log message
	 * 
	 * @param tag
	 * @param msg
	 * @param throwable
	 */
	public static void e(String tag, String msg, Throwable throwable) {
		if (sLevel > LEVEL_ERROR) {
			return;
		}
		android.util.Log.e(tag,buildMessage(msg));
	}

	protected static String buildMessage(String msg) {
		msg = null == msg ? "println msg is null" : msg;
		StackTraceElement caller = new Throwable().fillInStackTrace().getStackTrace()[2];
		msg = String.format("%s.%s(%s): %s", caller.getClassName(), caller.getMethodName(), caller.getLineNumber(), msg);
		if(isWrite){
			String date=sdf.format(new Date(System.currentTimeMillis()));
			LogCat.recordActionInfoLog(date+" "+msg);	
		}
		return msg;
	}

}

class LogCat {
	public static String filePath = BaseApplication.getInstance().getExternalCacheDir().getAbsolutePath()+"/Log.txt";
	public static ConcurrentLinkedQueue<String> tempQueue = new ConcurrentLinkedQueue<String>();

	public static synchronized void recordActionInfoLog(String ai) {
		tempQueue.add(ai);
		if (!WriteThread.isWriteThreadLive) {
			new WriteThread().start();
		}
	}

	/**
	 * 打开日志文件并写入日志
	 * @return
	 * **/
	public static void recordStringLog(String text) {// 新建或打开日志文件
		File file = new File(filePath);
		if (!file.exists()) {
			file.getParentFile().mkdirs();
			try {
				file.createNewFile();
			} catch (IOException e) {
				//System.err.println("行为日志：在" + filePath + "创建文件失败！");
				e.printStackTrace();
			}
		}
		try {
			FileWriter filerWriter = new FileWriter(file, true);// 后面这个参数代表是不是要接上文件中原来的数据，不进行覆盖
			BufferedWriter bufWriter = new BufferedWriter(filerWriter);
			bufWriter.write(text);
			bufWriter.newLine();
			bufWriter.close();
			filerWriter.close();
			//System.err.println("行为日志写入成功" + text);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 判断日志文件是否存在
	 * @return
	 */
	public static boolean isExitLogFile() {
		File file = new File(filePath);
		if (file.exists() && file.length() > 3) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 删除日志文件
	 */
	public static void deleteLogFile() {
		File file = new File(filePath);
		if (file.exists()) {
			file.delete();
		}
	}
}

class WriteThread extends Thread {
	public static boolean isWriteThreadLive = false;// 写日志线程是否已经在运行了
	public WriteThread() {
		isWriteThreadLive = true;
	}

	@Override
	public void run() {
		isWriteThreadLive = true;
		while (!LogCat.tempQueue.isEmpty()) {// 对列不空时
			try {
				// 写日志到SD卡
				LogCat.recordStringLog(LogCat.tempQueue.poll());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		isWriteThreadLive = false;// 队列中的日志都写完了，关闭线程
	}
}